
{%macro generate_setter(dict)-%}
    {%for key,value in dict.items()-%}
inline void Set{{key|capitalize}}({{value["type"]}} {{key}}) { {{key}}_ = {{key}}; }
    {%endfor-%}
{%endmacro-%}


{%macro generate_getter(dict)-%}
    {%for key,value in dict.items()-%}
inline {{value["type"]}} Get{{key|capitalize}}() const { return {{key}}_; }
    {%endfor-%}
{%endmacro-%}


{%macro generate_enum(key,value)%}
    {%for key1,value1 in value.items()-%}
        {%if value1 is string%}
/**
* @brief {{value1|wordwrap(wrapstring="\n* ")}}
*/
        {%endif%}
    {%endfor%}
{{key}} {
    {%for key1,value1 in value.items()-%}
        {%if value1 is not string%}
            {%for key2,value2 in value1.items()-%}
                {%for key3,value3 in value2.items()-%}
                    {%if loop.last -%}
{{key3|upper|indent(4,True)}}
                    {%else-%}
{{key3|upper|indent(4,True)}},
                    {%endif-%}
                {%endfor-%}
            {%endfor-%}
        {%endif%}
    {%endfor-%}
};
{%endmacro%}

{%macro generate_variable(key, value)%}
{{key}}{};
{%endmacro%}


{%macro generate_class(key,value,dict)%}
    {%for key1,value1 in value.items()-%}
        {%if key1 == "docs" and value1 is string%}
/**
* @brief {{value1|wordwrap(wrapstring="\n* ")}}
*/
        {%endif%}
    {%endfor%}
    {%if "inherits" in value.keys()%}
        {%for key1,value1 in value.items()-%}
            {%if key1 == "inherits"%}
{{key}} : public {{value1}}{
            {%endif%}
        {%endfor%}
    {%else%}
{{key}} {
    {%endif%}

{{"public:"|indent(4,True)}}
{{generate_default_constructor(key,value)|indent(8,True)-}}
{{generate_constructor(key,value,dict)|indent(8,True)-}}
{{generate_destructor(key,value)|indent(8,True)-}}
{{generate_copyconstructor(key,value)|indent(8,True)-}}
{{generate_copyassignment(key,value)|indent(8,True)-}}
{{generate_moveconstructor(key,value)|indent(8,True)-}}
{{generate_moveassignment(key,value)|indent(8,True)-}}

    {%for key1,value1 in value.items()-%}
        {%if value1 is not string-%}
            {%for key2,value2 in value1.items()-%}
                {%if value2 is iterable and value2 is not string-%}
                    {%for key3,value3 in value2.items()-%}
                            {% if "sequence" in key3-%}
                                {%for key4,value4 in value3.items()-%}
{{value4["type"]|indent(8,True)}} {{key4}}{};
                                {%endfor-%}
                                {{""}}
                            {%endif-%}
                            {% if "attributes" in key3 -%}
{{generate_setter(value3)|indent(8,True)}}
{{generate_getter(value3)|indent(8,True)}}
{{"protected:"|indent(4,True)}}
                                {%for key4,value4 in value3.items()-%}
{{"//"|indent(8,True)}}{{value4["docs"]|replace("\n"," ")}}
{{value4["type"]|indent(8,True)}} {{key4}}_{};
                                {%endfor-%}
                            {%endif-%}
                    {%endfor-%}
                {%endif%}
            {%endfor-%}
        {%endif%}
    {%endfor-%}
};
{%endmacro%}

{% macro generate_struct(key,value)%}
{{key}} {
    {%for key1,value1 in value.items()-%}
        {% if  key1.startswith("enum") -%}
            {{generate_enum(key1,value1)|indent(4,True)-}}
        {% elif key1.startswith("class") -%}
            {{generate_class(key1,value1)|indent(4,True)-}}
        {% elif key1.startswith("std::string") or key1.startswith("double") -%}
            {{generate_variable(key1,value1)|indent(4, True)-}}
        {%endif-%}
    {%endfor-%}
};
{%endmacro%}


{%macro generate_default_constructor(key,value)-%}
/**
* @brief default constructor
*/
{{key[6:]}}() = default;
{%endmacro-%}


{%macro generate_inputs(value,types)%}
    {%-for key1,value1 in value.items()-%}
        {%-if value1 is not string%}
            {%-for key2,value2 in value1.items()-%}
                {%-if value2 is iterable and value2 is not string-%}
                    {%-for key3,value3 in value2.items()-%}
                            {%- if "attributes" in key3 -%}
                                {%-for key4,value4 in value3.items()-%}
                                    {%if types == True%}
                                        {%-if loop.last%}
{{- value4["type"]}} {{key4}}
                                        {%-else%}
{{- value4["type"]}} {{key4}},
                                        {%-endif%}
                                    {%else%}
                                        {%-if loop.last%}
{{key4}}
                                        {%-else%}
{{key4}},
                                        {%-endif%}
                                    {%endif%}
                                {%-endfor-%}
                            {%-endif-%}
                    {%-endfor-%}
                {%-endif%}
            {%-endfor-%}
        {%-endif%}
    {%-endfor-%}
{%endmacro%}


{%macro generate_constructor(key,value,dict)-%}
/**
* @brief constructor
*/
{{key[6:]}}(
{%-set length = generate_inputs(value,True)-%}
{{-generate_inputs(value,True)-}}
{%-if "inherits" in value.keys()-%}
    {%-set base = value["inherits"]-%}
    {%-for basekey,basevalue in dict.items()-%}
        {%-if "class "+base == basekey-%}
            {%if length %}
,
            {%endif%}
{{-generate_inputs(basevalue,True)-}}
        {%endif%}
    {%endfor%}
{%endif%}
)
    {%-if "inherits" in value.keys()-%}
    {%-set base = value["inherits"]-%}
        {%-for basekey,basevalue in dict.items()-%}
            {%-if "class "+base == basekey-%}
:{{"\n"}}{{basekey[6:]|indent(4,True)}}({{-generate_inputs(basevalue,False)-}}) {}
        {%endif%}
        {%endfor%}
    {%-else-%}
{};
    {%endif%}
{%endmacro%}

{%macro generate_destructor(key,value)-%}
/**
* @brief destructor
*/
~{{key[6:]}}() = default;
{%endmacro-%}

{%macro generate_copyconstructor(key,value)-%}
/**
* @brief copy constructor
*/
{{key[6:]}}(const {{key[6:]}}& {{key[8:]|lower}}) = delete;
{%endmacro-%}

{%macro generate_copyassignment(key,value)-%}
/**
* @brief copy assignment
*/
{{key[6:]}}& operator=(const {{key[6:]}}& {{key[8:]|lower}}) & = delete;
{%endmacro-%}


{%macro generate_moveconstructor(key,value)-%}
/**
* @brief move constructor
*/
{{key[6:]}}({{key[6:]}}&& {{key[8:]|lower}}) = delete;
{%endmacro-%}

{%macro generate_moveassignment(key,value)-%}
/**
* @brief move assignment
*/
{{key[6:]}}& operator=({{key[6:]}}&& {{key[8:]|lower}}) & = delete;
{%endmacro-%}

{%macro generate_datastructs(data)%}
    {%for key,value in data.items()-%}
        {% if  key.startswith("enum") -%}
            {{generate_enum(key,value)|indent(4,True)}}
        {% elif key.startswith("class") -%}
            {{generate_class(key,value,data)|indent(4,True)}}
        {% elif key.startswith("std::string") or key.startswith("double")-%}
            {{generate_variable(key,value)|indent(4, True)}}
        {% elif key.startswith("struct") -%}
            {{generate_struct(key,value)|indent(4, True)}}
        {%endif-%}
    {%endfor-%}
{%endmacro%}

